﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;


namespace Light
{
    /// <summary>
    /// 马路上的车。自己知道自己的速度，和车道。
    /// 可以根据交通灯和马路上的车流自己移动
    /// </summary>
    partial class Car : UIElement
    {
        public int Lane;       // 车道,由车道确定车辆行驶的路线
        int RunningTime;  // 车辆播放动画的时间
        Storyboard sb;  // 车辆行走路线动画故事版
        Road road;      // 车辆所属于的车道
        List<Car> OldCollisionList;
        List<Car> CurrentCollisionList;
        int id;
        static int g_id = 0;

        public Car( Canvas p, Road r, PathGeometry pg, string CarName, int l = 0, int t = 5000 )
        {
            id = g_id;
            double rotation = 0;
            double rotatedelay = 0;
            double angle = 0;
            double scaleFrom = 1;
            double scaleTo = 0.7;
            g_id++;

            parentCanvas = p;
            road = r;
            Lane = l;
            RunningTime = t;

            switch ( Lane )
            {
                case 0: 
                    angle = 90;
                    rotation = 90;
                    scaleFrom = 0.5;
                    scaleTo = 0.7;
                    break;
                case 1:
                    angle = 90;
                    scaleFrom = 0.5;
                    scaleTo = 1;
                    break;
                case 2:
                    angle = 90;
                    rotation = -90;
                    scaleFrom = 0.5;
                    scaleTo = 0.7;
                    break;
                case 3:
                    angle = 180;
                    rotation = 90;
                    scaleFrom = 0.7;
                    scaleTo = 0.5;
                    break;
                case 4:
                    angle = 180;
                    scaleFrom = 0.7;
                    scaleTo = 0.7;
                    break;
                case 5:
                    angle = 180;
                    rotation = -90;
                    scaleFrom = 0.7;
                    scaleTo = 1;
                    break;
                case 6:
                    angle = -90;
                    rotation = 90;
                    scaleFrom = 1;
                    scaleTo = 0.7;
                    break;
                case 7:
                    angle = -90;
                    rotation = 0;
                    scaleFrom = 1;
                    scaleTo = 0.5;
                    break;
                case 8:
                    angle = -90;
                    rotation = -90;
                    scaleFrom = 1;
                    scaleTo = 0.7;
                    break;
                case 9:
                    rotation = -90;
                    scaleFrom = 0.7;
                    scaleTo = 0.5;
                    break;
                case 10:
                    scaleFrom = 0.7;
                    scaleTo = 0.7;
                    break;
                case 11:
                    rotation = 90;
                    scaleFrom = 0.7;
                    scaleTo = 1;
                    break;
            }



            OldCollisionList = new List<Car>();
            CurrentCollisionList = new List<Car>();

            PathGeometry path = pg;


            System.Windows.Duration duration = new System.Windows.Duration( TimeSpan.FromMilliseconds( RunningTime ) );

            DoubleAnimationUsingPath dapX = new DoubleAnimationUsingPath();
            dapX.PathGeometry = pg;
            dapX.Source = PathAnimationSource.X;
            dapX.Duration = duration;


            DoubleAnimationUsingPath dapY = new DoubleAnimationUsingPath();
            dapY.PathGeometry = pg;
            dapY.Source = PathAnimationSource.Y;
            dapY.Duration = duration;

            DoubleAnimation dapR = new DoubleAnimation();
            dapR.BeginTime = dapR.BeginTime + TimeSpan.FromSeconds( rotatedelay );
            dapR.By = rotation;
            dapR.Duration = new System.Windows.Duration( TimeSpan.FromMilliseconds( RunningTime/2 ) );


            DoubleAnimation dapSX = new DoubleAnimation();
            dapSX.From = scaleFrom;
            dapSX.To = scaleTo;
            dapSX.Duration = duration;

            DoubleAnimation dapSY = new DoubleAnimation();
            dapSY.From = scaleFrom;
            dapSY.To = scaleTo;
            dapSY.Duration = new System.Windows.Duration( TimeSpan.FromMilliseconds( RunningTime ) ); ;


            ScaleTransform st = new ScaleTransform();
            st.CenterX = 5;
            st.CenterY = 10;

            RotateTransform rt = new RotateTransform();
            rt.CenterX = 5;
            rt.CenterY = 10;
            rt.Angle = angle;

            TranslateTransform transform = new TranslateTransform( 0, 0 );

            TranslateTransform tt = new TranslateTransform();
            tt.X = image.Width/2;
            tt.Y = image.Height/2;

            TransformGroup group = new TransformGroup();


            group.Children.Add( st );
            group.Children.Add( rt );
            group.Children.Add( transform );



            this.image.RenderTransform = group;

            parentCanvas.RegisterName( CarName + "tt", tt );
            parentCanvas.RegisterName( CarName + "t", transform );
            parentCanvas.RegisterName( CarName + "st", st );
            parentCanvas.RegisterName( CarName + "rt", rt );


            sb = new Storyboard();

            Storyboard.SetTargetName( dapX, CarName + "t" );
            Storyboard.SetTargetName( dapY, CarName + "t" );
            Storyboard.SetTargetName( dapR, CarName + "rt" );
            Storyboard.SetTargetName( dapSX, CarName + "st" );
            Storyboard.SetTargetName( dapSY, CarName + "st" );

            Storyboard.SetTargetProperty( dapX, new PropertyPath( TranslateTransform.XProperty ) );
            Storyboard.SetTargetProperty( dapY, new PropertyPath( TranslateTransform.YProperty ) );
            Storyboard.SetTargetProperty( dapR, new PropertyPath( RotateTransform.AngleProperty ) );
            Storyboard.SetTargetProperty( dapSX, new PropertyPath( ScaleTransform.ScaleXProperty ) );
            Storyboard.SetTargetProperty( dapSY, new PropertyPath( ScaleTransform.ScaleYProperty ) );

            sb.Children.Add( dapX );
            sb.Children.Add( dapY );
            sb.Children.Add( dapR );
            sb.Children.Add( dapSX );
            sb.Children.Add( dapSY );

            LoadImage();
            CarBegin();
            
        }



        public override void OnAnimate()
        {
            if ( ClockState.Filling == sb.GetCurrentState( parentCanvas ) )
            {
                parentCanvas.Children.Remove( this.image );
                road.laneCar[ Lane ].Remove( this );
            }



            // 根据自己的位置和红绿灯情况判断是否暂停
            List<TrafficLight> lights = road.LightList;
            TrafficLight light = lights[ Lane / 3 ];        // 自己车道的灯
            LightStatus status = light.Status;              // 自己车道灯的状态

            if (! ( Lane % 3 == 0 
                || ( ( status == LightStatus.LEFT_FLASH || status == LightStatus.LEFT ) && Lane % 3 == 2 ) 
                || ( ( status == LightStatus.STRAIGHT_FLASH || status == LightStatus.STRAIGHT ) && Lane % 3 == 1 ) ) )
            {
                if ( sb.GetCurrentProgress( parentCanvas ) < 0.25 )
                {
                    this.CarPause();
                    return;
                }
            }


            //if ( ( status == LightStatus.RED && Lane % 3 != 0 )
            //    || ( ( status == LightStatus.LEFT || status == LightStatus.LEFT_FLASH ) && Lane % 3 == 1 ) 
            //    || ( ( status == LightStatus.STRAIGHT || status == LightStatus.STRAIGHT_FLASH ) && Lane % 3 == 2 ) )
            //{
            //    //this.CarPause();
            //    //return;
            //    if ( sb.GetCurrentProgress( parentCanvas ) < 0.25 )
            //    {
            //        this.CarPause();
            //        return;
            //    }
            //}

            // 根据其他车的位置移动自己
            CurrentCollisionList = GetCollidedList();
            if ( CurrentCollisionList.Count == 0 )
            {
                this.CarResume();
                return;
            }
            int minid = this.id;
            foreach ( Car car in CurrentCollisionList )
            {

                if ( car.id < minid )
                {
                    minid = car.id;
                }
            }

            if ( minid != this.id )
            {
                this.CarPause();
            }

            foreach ( Car car in CurrentCollisionList )
            {
                if ( car.id == minid )
                {
                    car.CarResume();
                    CurrentCollisionList.Remove( car );
                    break;
                }
            }

           

            //CarResume();
        }

        // 得到碰撞包围圆
        public void GetBoundingCircle( ref double radius, ref double centerX, ref double centerY )
        {
            double width, height;

            TransformGroup g = image.RenderTransform as TransformGroup;

            Point pt = g.Transform( new Point( image.Width / 2, image.Height / 2 ) );
            Point pt2 = g.Transform( new Point( 0, 0 ) );
            ScaleTransform scale = g.Children.ElementAt( 0 ) as ScaleTransform;


            width = image.Width * scale.ScaleX;
            height = image.Height * scale.ScaleY;

            centerX = pt.X;
            centerY = pt.Y;

            radius = width > height ? width : height;

        }

        // 得到碰撞列表，如果列表为空，表明不与其他人碰撞
        public List<Car> GetCollidedList()
        {
            List<Car> cars = road.CarList;
            List<Car> CollisionCars = new List<Car>();
            double myx, myy, myr;
            double x, y, r;
            double d = 0;
            x = y = r = 0;
            myx = myy = myr = 0;

            foreach ( Car car in cars )
            {
                car.GetBoundingCircle( ref r, ref x, ref y );
                this.GetBoundingCircle( ref myr, ref myx, ref myy );
                d = GetDistance( x, y, myx, myy );
                if ( Math.Abs( ( r + myr ) ) >= d && car != this &&  this.Lane == car.Lane )
                {
                    CollisionCars.Add( car );
                }

            }
            return CollisionCars;

        }


        private double GetDistance( double x1, double y1, double x2, double y2 )
        {
            return Math.Sqrt( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) );
        }

        // 车辆动画开始
        public void CarBegin()
        {
            sb.Begin( parentCanvas, true );
        }

        // 车辆暂停行驶
        public void CarPause()
        {
            if ( !sb.GetIsPaused( parentCanvas ) )
            {
                sb.Pause( parentCanvas );
            }

        }

        // 车辆恢复行驶
        public void CarResume()
        {
            if ( sb.GetIsPaused( parentCanvas ) )
            {
                sb.Resume( parentCanvas );
            }
        }


        // 车辆移除
        public void RemoveCar()
        {
            parentCanvas.Children.Remove( image );
        }

    }
}
